package myself.doit.schedule.v1;

import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Created by bjliuyong on 2017/1/10.
 */
public class ReschedulingRunnable implements Runnable {

    private final Runnable delegate;

    private  CronSequenceGenerator cronSequenceGenerator ;

    private ScheduledExecutorService scheduledExecutorService ;

    private Date actualExecutionTime = new Date() ;

    public void schedule() {
        Date nextTime = cronSequenceGenerator.next(actualExecutionTime) ;
        long delay = nextTime.getTime() - actualExecutionTime.getTime();
        scheduledExecutorService.schedule(this , delay , TimeUnit.MILLISECONDS);
    }

    public ReschedulingRunnable(ScheduledExecutorService executorService , Runnable delegate, String cronExp) {
        this.delegate = delegate;
        this.cronSequenceGenerator = new CronSequenceGenerator(cronExp);
        this.scheduledExecutorService = executorService ;
    }


    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see Thread#run()
     */
    @Override
    public void run() {


        actualExecutionTime = new Date();
        this.delegate.run();
        schedule();

    }
}
